<?php
declare (strict_types=1);
namespace app\middleware;

use app\common\lib\Aes;

class Auth
{
    /**
     * 处理请求
     * @param \think\Request $request
     * @param \Closure       $next
     * @return mixed
     */
    public function handle($request, \Closure $next)
    {
        header('Access-Control-Allow-Origin:*');
        header('Content-Type:application/json; charset=utf-8');
        $callback = $request->param('callback', '');
        $param = $request->param();
        $debug = $param['_debug'] ?? ($_GET['_debug'] ?? ($_COOKIE['_debug'] ?? ''));
        if ($debug === 'param') {
            print_r($param);
            exit;
        }
        $json = get_json_params();
        if ($debug === 'json') {
            print_r($json);
            exit;
        }
        if (!empty($json)) {
            $param = array_merge($param, $json);
        }
        if ($debug === 'total') {
            print_r($param);
            exit;
        }
        if ($debug === md5('is_test_' . date('Ymd'))) {
            return $next($request);
        }
        if ($debug !== md5('api_debug_' . date('Ymd'))) {
            $flag = $this->checkSign($param);
            if ($flag !== true) {
                echo eJson('签名错误', 444, [], $callback);
                exit;
            }
        }
        $noLogin = config('app.NO_LOGIN');
        if ($debug === 'noLogin') {
            print_r($noLogin);
            exit;
        }
        $class = strtolower($request->controller());
        $action = strtolower($request->action());
        $token = $request->header('token');
        if (!empty($noLogin[$class]) && ($noLogin[$class] === '*' || in_array($action, $noLogin[$class])) && empty($token)) {
            return $next($request);
        }
        if (empty($token) && (empty($noLogin[$class]) || ($noLogin[$class] !== '*' && !in_array($action, $noLogin[$class])))) {
            echo eJson('请先登录', 441, [], $callback);
            exit;
        }
        $token = $this->dataDecrypt($token);
        if (empty($token)) {
            echo eJson('非法操作', 443, [], $callback);
            exit;
        }
        $token_expire = env('app.token_expire', 7200);
        if ($token_expire > 0 && time() - $token['login_time'] > $token_expire) {
            echo eJson('登录超时', 442, [], $callback);
            exit;
        }
        $request->user_id = $token['id']; // 当前登录用户ID
        return $next($request);
    }

    /**
     * 验证签名
     * @author 贺强
     * @time   2019-05-28 15:14:53
     * @param array $data 参与验证的数据
     * @return bool         返回验证结果
     */
    private function checkSign(&$data = []): bool
    {
        $sign = $data['sign'] ?? '';
        $_debug = $data['_debug'] ?? '';
        unset($data['sign'], $data['callback'], $data['_debug']);
        // 根据传递的参数生成新的校验码
        ksort($data);
        $str = urldecode(http_build_query($data));
        if ($_debug === 'param_str') {
            echo $str;
            exit;
        }
        $str = str_replace(' ', '+', $str);
        $str .= '|' . env('app.secret', '');
        if ($_debug === 'param_str2') {
            echo $str;
            exit;
        }
        $str = md5($str);
        if ($_debug === 'sign') {
            echo $str;
            exit;
        }
        if ($sign === $str) {
            return true;
        }
        return false;
    }

    /**
     * 数据AES解密
     * @author 贺强
     * @time   2021-03-23 15:58:50
     * @param string $ciphertext 要解密的串
     * @return mixed             返回解密后的数据
     */
    private function dataDecrypt($ciphertext)
    {
        $data = '';
        if (!empty($ciphertext)) {
            $data = (new Aes())->decrypt($ciphertext);
            if (!$data) {
                return false;
            }
            $param = json_decode($data, true);
            if (json_last_error() == JSON_ERROR_NONE) {
                $data = $param;
            }
        }
        return $data;
    }
}
